#ifndef CHANNEL_H
#define CHANNEL_H

#pragma once
#include "Socket.h"
#include <functional>
class Epoll;
/*
这个类就是为Epoll量身打造的, 目的是将channel挂载到epoll_events.events上
控制套接字的读写事件
所有的事情都有是这个类具体来完成
*/

class Channel
{
public:
    Channel(Epoll* ep, int fd);
    ~Channel();
    // 分发事件
    void handleEvent();
    // 在这个类创建出来的时候，就创建绑定上回调函数，这样就不用区分是不是listenfd了
    void setReadCb(std::function<void()> fun);
    // 处理对端发送过来的消息
    void onMessage();
    void setRevents(uint32_t revents) {revents_ = revents;}
    uint32_t getEvents() {return events_;}
    uint32_t getRevents() {return revents_;}
    bool inEpoll() {return inEpoll_;}
    // 标记该套接字已经上树
    void setInEpoll() {this->inEpoll_ = true;}
    // 设置边缘触发
    void setET();
    // 取消关注所有事件
    void disalbeAll();
    // 让epoll_wait监听fd_读事件
    void enableReading();
    void disableReading();
    void enableWriting();
    void disableWriting();

    int getFd() {return fd_;}
    // bool isListen() {return isListen_;}

    void setWriteCb(std::function<void()> fun) {
        writeCallBack_ = fun;
    }
    void setExitCb(std::function<void()> fun) {
        exitCb_ = fun;
    }
    void setErrorCb(std::function<void()> fun) {
        errorCb_ = fun;
    }
private:
    //  我现在不理解为什么Channel要拥有一个单独的文件描述符
    // 不应该保留一个指向Socket的指针吗？
    // 这个fd不是我的
    int fd_ = -1; // 一对一
    Epoll* ep_ = nullptr; // 一对多
    uint32_t events_ = 0;   // fd_关心的事件listenfd和clientfd需要监视EPOLLIN，clientfd还可能需要监视EPOLLOUT。
    uint32_t revents_ = 0;  // fd 已经发生的事件
    bool inEpoll_ = false;
    // 负责分发是连接事件和读事件
    std::function<void()> readCallBack_;
    std::function<void()> writeCallBack_;

    std::function<void()> exitCb_;
    std::function<void()> errorCb_;
};

#endif